]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOS9/Mac OS Test Searcher.c
mDNSResponder-567.tar.gz
[apple/mdnsresponder.git] / mDNSMacOS9 / Mac OS Test Searcher.c
1 /* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include <stdio.h> // For printf()
19 #include <Events.h> // For WaitNextEvent()
20 #include <SIOUX.h> // For SIOUXHandleOneEvent()
21
22 #include "mDNSEmbeddedAPI.h" // Defines the interface to the client layer above
23 #include "mDNSMacOS9.h" // Defines the specific types needed to run mDNS on this platform
24
25 typedef struct
26 {
27 OTLIFO serviceinfolist;
28 Boolean headerPrinted;
29 Boolean lostRecords;
30 } SearcherServices;
31
32 typedef struct { ServiceInfo i; mDNSBool add; mDNSBool dom; OTLink link; } linkedServiceInfo;
33
34 // These don't have to be globals, but their memory does need to remain valid for as
35 // long as the search is going on. They are declared as globals here for simplicity.
36 #define RR_CACHE_SIZE 1000
37 static CacheEntity rrcachestorage[RR_CACHE_SIZE];
38 static mDNS mDNSStorage;
39 static mDNS_PlatformSupport PlatformSupportStorage;
40 static SearcherServices services;
41 static DNSQuestion browsequestion, domainquestion;
42
43 // PrintServiceInfo prints the service information to standard out
44 // A real application might want to do something else with the information
45 static void PrintServiceInfo(SearcherServices *services)
46 {
47 OTLink *link = OTReverseList(OTLIFOStealList(&services->serviceinfolist));
48
49 while (link)
50 {
51 linkedServiceInfo *ls = OTGetLinkObject(link, linkedServiceInfo, link);
52 ServiceInfo *s = &ls->i;
53
54 if (!services->headerPrinted)
55 {
56 printf("%-55s Type Domain IP Address Port Info\n", "Name");
57 services->headerPrinted = true;
58 }
59
60 if (ls->dom)
61 {
62 char c_dom[MAX_ESCAPED_DOMAIN_NAME];
63 ConvertDomainNameToCString(&s->name, c_dom);
64 if (ls->add) printf("%-55s available for browsing\n", c_dom);
65 else printf("%-55s no longer available for browsing\n", c_dom);
66 }
67 else
68 {
69 domainlabel name;
70 domainname type, domain;
71 char c_name[MAX_DOMAIN_LABEL+1], c_type[MAX_ESCAPED_DOMAIN_NAME], c_dom[MAX_ESCAPED_DOMAIN_NAME], c_ip[20];
72 DeconstructServiceName(&s->name, &name, &type, &domain);
73 ConvertDomainLabelToCString_unescaped(&name, c_name);
74 ConvertDomainNameToCString(&type, c_type);
75 ConvertDomainNameToCString(&domain, c_dom);
76 sprintf(c_ip, "%d.%d.%d.%d", s->ip.ip.v4.b[0], s->ip.ip.v4.b[1], s->ip.ip.v4.b[2], s->ip.ip.v4.b[3]);
77
78 printf("%-55s %-16s %-14s ", c_name, c_type, c_dom);
79 if (ls->add) printf("%-15s %5d %#s\n", c_ip, mDNSVal16(s->port), s->TXTinfo);
80 else printf("Removed\n");
81 }
82
83 link = link->fNext;
84 OTFreeMem(ls);
85 }
86 }
87
88 // When the name, address, port, and txtinfo for a service is found, FoundInstanceInfo()
89 // enqueues a record for PrintServiceInfo() to print.
90 // Note, a browsing application would *not* normally need to get all this information --
91 // all it needs is the name, to display to the user.
92 // Finding out the address, port, and txtinfo should be deferred to the time that the user
93 // actually needs to contact the service to use it.
94 static void FoundInstanceInfo(mDNS *const m, ServiceInfoQuery *query)
95 {
96 SearcherServices *services = (SearcherServices *)query->ServiceInfoQueryContext;
97 linkedServiceInfo *info = (linkedServiceInfo *)(query->info);
98 if (query->info->ip.type == mDNSAddrType_IPv4)
99 {
100 mDNS_StopResolveService(m, query); // For this test code, one answer is sufficient
101 OTLIFOEnqueue(&services->serviceinfolist, &info->link);
102 OTFreeMem(query);
103 }
104 }
105
106 // When a new named instance of a service is found, FoundInstance() is called.
107 // In this sample code we turn around and immediately issue a query to resolve that service name to
108 // find its address, port, and txtinfo, but a normal browing application would just display the name.
109 static void FoundInstance(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
110 {
111 #pragma unused (question)
112 SearcherServices *services = (SearcherServices *)question->QuestionContext;
113 linkedServiceInfo *info;
114
115 debugf("FoundInstance %##s PTR %##s", answer->name->c, answer->rdata->u.name.c);
116
117 if (answer->rrtype != kDNSType_PTR) return;
118 if (!services) { debugf("FoundInstance: services is NULL"); return; }
119
120 info = (linkedServiceInfo *)OTAllocMem(sizeof(linkedServiceInfo));
121 if (!info) { services->lostRecords = true; return; }
122
123 info->i.name = answer->rdata->u.name;
124 info->i.InterfaceID = answer->InterfaceID;
125 info->i.ip.type = mDNSAddrType_IPv4;
126 info->i.ip.ip.v4 = zerov4Addr;
127 info->i.port = zeroIPPort;
128 info->add = AddRecord;
129 info->dom = mDNSfalse;
130
131 if (!AddRecord) // If TTL == 0 we're deleting a service,
132 OTLIFOEnqueue(&services->serviceinfolist, &info->link);
133 else // else we're adding a new service
134 {
135 ServiceInfoQuery *q = (ServiceInfoQuery *)OTAllocMem(sizeof(ServiceInfoQuery));
136 if (!q) { OTFreeMem(info); services->lostRecords = true; return; }
137 mDNS_StartResolveService(m, q, &info->i, FoundInstanceInfo, services);
138 }
139 }
140
141 static void FoundDomain(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
142 {
143 #pragma unused (m)
144 #pragma unused (question)
145 SearcherServices *services = (SearcherServices *)question->QuestionContext;
146 linkedServiceInfo *info;
147
148 debugf("FoundDomain %##s PTR %##s", answer->name->c, answer->rdata->u.name.c);
149
150 if (answer->rrtype != kDNSType_PTR) return;
151 if (!services) { debugf("FoundDomain: services is NULL"); return; }
152
153 info = (linkedServiceInfo *)OTAllocMem(sizeof(linkedServiceInfo));
154 if (!info) { services->lostRecords = true; return; }
155
156 info->i.name = answer->rdata->u.name;
157 info->i.InterfaceID = answer->InterfaceID;
158 info->i.ip.type = mDNSAddrType_IPv4;
159 info->i.ip.ip.v4 = zerov4Addr;
160 info->i.port = zeroIPPort;
161 info->add = AddRecord;
162 info->dom = mDNStrue;
163
164 OTLIFOEnqueue(&services->serviceinfolist, &info->link);
165 }
166
167 // YieldSomeTime() just cooperatively yields some time to other processes running on classic Mac OS
168 static Boolean YieldSomeTime(UInt32 milliseconds)
169 {
170 extern Boolean SIOUXQuitting;
171 EventRecord e;
172 WaitNextEvent(everyEvent, &e, milliseconds / 17, NULL);
173 SIOUXHandleOneEvent(&e);
174 return(SIOUXQuitting);
175 }
176
177 int main()
178 {
179 mStatus err;
180 Boolean DoneSetup = false;
181 void *tempmem;
182
183 SIOUXSettings.asktosaveonclose = false;
184 SIOUXSettings.userwindowtitle = "\pMulticast DNS Searcher";
185 SIOUXSettings.rows = 40;
186 SIOUXSettings.columns = 132;
187
188 printf("Multicast DNS Searcher\n\n");
189 printf("This software reports errors using MacsBug breaks,\n");
190 printf("so if you don't have MacsBug installed your Mac may crash.\n\n");
191 printf("******************************************************************************\n");
192
193 err = InitOpenTransport();
194 if (err) { debugf("InitOpenTransport failed %d", err); return(err); }
195
196 err = mDNS_Init(&mDNSStorage, &PlatformSupportStorage, rrcachestorage, RR_CACHE_SIZE,
197 mDNS_Init_DontAdvertiseLocalAddresses, mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
198 if (err) return(err);
199
200 // Make sure OT has a large enough memory pool for us to draw from at OTNotifier (interrupt) time
201 tempmem = OTAllocMem(0x10000);
202 if (tempmem) OTFreeMem(tempmem);
203 else printf("**** Warning: OTAllocMem couldn't pre-allocate 64K for us.\n");
204
205 services.serviceinfolist.fHead = NULL;
206 services.headerPrinted = false;
207 services.lostRecords = false;
208
209 while (!YieldSomeTime(35))
210 {
211 #if MDNS_ONLYSYSTEMTASK
212 // For debugging, use "#define MDNS_ONLYSYSTEMTASK 1" and call mDNSPlatformIdle() periodically.
213 // For shipping code, don't define MDNS_ONLYSYSTEMTASK, and you don't need to call mDNSPlatformIdle()
214 extern void mDNSPlatformIdle(mDNS *const m);
215 mDNSPlatformIdle(&mDNSStorage); // Only needed for debugging version
216 #endif
217 if (mDNSStorage.mDNSPlatformStatus == mStatus_NoError && !DoneSetup)
218 {
219 domainname srvtype, srvdom;
220 DoneSetup = true;
221 printf("\nSending mDNS service lookup queries and waiting for responses...\n\n");
222 MakeDomainNameFromDNSNameString(&srvtype, "_http._tcp.");
223 MakeDomainNameFromDNSNameString(&srvdom, "local.");
224 err = mDNS_StartBrowse(&mDNSStorage, &browsequestion, &srvtype, &srvdom, mDNSInterface_Any, mDNSfalse, FoundInstance, &services);
225 if (err) break;
226 err = mDNS_GetDomains(&mDNSStorage, &domainquestion, mDNS_DomainTypeBrowse, NULL, mDNSInterface_Any, FoundDomain, &services);
227 if (err) break;
228 }
229
230 if (services.serviceinfolist.fHead)
231 PrintServiceInfo(&services);
232
233 if (services.lostRecords)
234 {
235 services.lostRecords = false;
236 printf("**** Warning: Out of memory: Records have been missed.\n");
237 }
238 }
239
240 mDNS_StopBrowse(&mDNSStorage, &browsequestion);
241 mDNS_Close(&mDNSStorage);
242 return(0);
243 }